package com.openthinks.joyniproject.utils.concurrent;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * 并发Map. 该Map可以实现读写互斥,保证数据唯一且线程安全
 * @since 
 *		v1.0
 * @version
 * 		v1.0, 2011-02-01 15:43:49
 * @author 
 *		Cloud
 * @param <K>
 * 			键
 * @param <V>
 * 			值
 */
public class ConcurrentMap<K, V> {

	/**
	 * 读写锁
	 */
	private ReadWriteLock lock = new ReentrantReadWriteLock();
	
	/**
	 * 读锁
	 */
	private Lock readLock = lock.readLock();
	
	/**
	 * 写锁
	 */
	private Lock writeLock = lock.writeLock();
	
	/**
	 * 存储数据使用Map
	 */
	private Map<K, V> map = new HashMap<K, V>();
	
	/**
	 * 存入数据
	 * @param key
	 * 			键
	 * @param value
	 * 			值
	 */
	public void put(K key, V value) {
		
		try {
			writeLock.lock();
			map.put(key, value);
		} finally {
			writeLock.unlock();
		}	
	}
	
	/**
	 * 根据key获取value
	 * @param key
	 * 			键
	 * @return
	 */
	public V get(K key) {
		
		try {
			readLock.lock();
			return map.get(key);
		} finally {
			readLock.unlock();
		}	
	}
	
	/**
	 * 根据key删除对应value
	 * @param key
	 * 			键
	 * @return
	 * 			被删除的数据
	 */
	public V remove(K key) {
		
		try {
			writeLock.lock();
			return map.remove(key);
		} finally {
			writeLock.unlock();
		}	
	}
	
	/**
	 * 清空数据
	 */
	public void clean() {
		
		try {
			writeLock.lock();
			map.clear();
		} finally {
			writeLock.unlock();
		}
	}
	
	/**
	 * 获取数量
	 * @return
	 */
	public int size() {
		
		try {
			readLock.lock();
			return map.size();
		} finally {
			readLock.unlock();
		}	
	}
	
	/**
	 * 获取所有key
	 * @return
	 */
	public List<K> getKeys() {
		
		try {
			readLock.lock();
			List<K> list = new ArrayList<K>(map.size());
			Set<K> keys = map.keySet();
			for (K key : keys) {
				list.add(key);
			}
			
			return list;
		} finally {
			readLock.unlock();
		}	
	}
}
